package cn.hoichun.news.Service.Impl;

import cn.hoichun.news.Domain.Rating;
import cn.hoichun.news.Domain.User;
import cn.hoichun.news.Mapper.ScoreMapper;
import cn.hoichun.news.Mapper.UserMapper;
import cn.hoichun.news.Service.IUserService;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Hoichun
 */
@Service
public class UserServiceImpl implements IUserService {

    private final UserMapper userMapper;
    private final ScoreMapper scoreMapper;

    public UserServiceImpl(UserMapper userMapper, ScoreMapper scoreMapper) {
        this.userMapper = userMapper;
        this.scoreMapper = scoreMapper;
    }

    @Override
    public List<User> listAllUsers() {
        return userMapper.findAll();
    }

    @Override
    public User findUserById(int id) {
        return userMapper.findById(id);
    }

    @Override
    public List<User> getSimilarUsers(int userId) {
        HashMap<String, Double> interestMap = new HashMap<>();
        for (Rating rating :
                scoreMapper.selectAllRatings()) {
            interestMap.put(rating.getUserId() + "," + rating.getArticleId(), rating.getInterest());
        }
        HashMap<String, Double> matrixMap = new HashMap<>();
        double xy, x2, y2;
        for (int j :
                scoreMapper.selectAllUserId()) {
            if (userId != j) {
                xy = x2 = y2 = 0.;
                for (Integer k :
                        scoreMapper.selectAllArticleId()) {
                    xy += (interestMap.getOrDefault(userId + "," + k, 0.)) * (interestMap.getOrDefault(
                            j + "," + k,
                            0.
                    ));
                    x2 += (interestMap.getOrDefault(userId + "," + k, 0.)) * (interestMap.getOrDefault(
                            userId + "," + k,
                            0.
                    ));
                    y2 += (interestMap.getOrDefault(j + "," + k, 0.)) * (interestMap.getOrDefault(j + "," + k, 0.));
                }
                matrixMap.put(String.valueOf(j), xy / (Math.sqrt(x2) * Math.sqrt(y2)));
            }
        }
        List<Map.Entry<String, Double>> list = new ArrayList<>(matrixMap.entrySet());
        list.sort((o1, o2) -> o2.getValue().compareTo(o1.getValue()));
        List<User> userList = new ArrayList<>();
        for (Map.Entry<String, Double> entry :
                list) {
            userList.add(userMapper.findById(Integer.parseInt(entry.getKey())));
        }
        return userList;
    }
}
